<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Three.js 固定射线检测距离(20mm)</title>
    <style>
        body { margin: 0; overflow: hidden; }
        canvas { display: block; }
        #controls {
            position: absolute;
            top: 10px;
            left: 10px;
            background: rgba(255,255,255,0.7);
            padding: 10px;
            border-radius: 5px;
        }
        #result {
            margin-top: 10px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div id="controls">
        <div>
            <label for="distance">设置两物体距离(mm): </label>
            <input type="number" id="distance" value="10" min="0" max="100" step="1">
            <button id="checkBtn">检测是否在20mm范围内</button>
        </div>
        <div id="result">等待检测...</div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
    <script>
        // 初始化场景、相机和渲染器
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // 创建两个立方体
        const cubeSize = 1; // 1单位 = 1厘米(假设)
        const geometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
        
        // 立方体A(发射射线)
        const cubeAMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cubeA = new THREE.Mesh(geometry, cubeAMaterial);
        cubeA.position.set(-5, 0, 0);
        scene.add(cubeA);
        
        // 立方体B(检测目标)
        const cubeBMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
        const cubeB = new THREE.Mesh(geometry, cubeBMaterial);
        cubeB.position.set(5, 0, 0);
        scene.add(cubeB);

        // 设置相机位置
        camera.position.z = 15;
        camera.position.y = 5;
        camera.lookAt(0, 0, 0);

        // 固定射线检测距离为20mm(2厘米)
        const fixedRayLength = 2; // 20mm = 2cm
        
        // 创建射线辅助可视化(固定长度20mm)
        let rayHelper = new THREE.ArrowHelper(
            new THREE.Vector3(1, 0, 0),
            cubeA.position,
            fixedRayLength,
            0x00ff00,
            0.2, // 头部长度
            0.1  // 头部宽度
        );
        scene.add(rayHelper);

        // 获取DOM元素
        const distanceInput = document.getElementById('distance');
        const checkBtn = document.getElementById('checkBtn');
        const resultDiv = document.getElementById('result');

        // 检测按钮点击事件
        checkBtn.addEventListener('click', () => {
            const distanceMm = parseFloat(distanceInput.value);
            const distanceCm = distanceMm / 10; // 转换为厘米
            
            // 更新立方体B的位置(距离可自由调整)
            cubeB.position.x = cubeA.position.x + distanceCm;
            
            // 执行射线检测(使用固定的20mm检测距离)
            performRaycast(fixedRayLength, distanceCm);
        });

        // 执行射线检测函数
        function performRaycast(rayLength, actualDistance) {
            // 创建射线
            const raycaster = new THREE.Raycaster();
            const direction = new THREE.Vector3(1, 0, 0); // 沿X轴正方向
            raycaster.set(cubeA.position, direction);
            raycaster.far = rayLength; // 固定检测距离20mm
            
            // 检测与立方体B的碰撞
            const intersects = raycaster.intersectObject(cubeB);
            
            const actualDistanceMm = actualDistance * 10; // 转换回毫米
            
            if (intersects.length > 0) {
                resultDiv.textContent = `立方体B在20mm射线范围内(实际距离: ${actualDistanceMm.toFixed(1)}mm)`;
                resultDiv.style.color = 'green';
                cubeBMaterial.color.set(0x00ff00); // 变绿色表示在范围内
            } else {
                resultDiv.textContent = `立方体B不在20mm射线范围内(实际距离: ${actualDistanceMm.toFixed(1)}mm)`;
                resultDiv.style.color = 'red';
                cubeBMaterial.color.set(0x0000ff); // 恢复蓝色
            }
        }

        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }
        animate();

        // 窗口大小调整
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // 初始检测
        performRaycast(fixedRayLength, 1); // 初始距离1单位(10mm)
    </script>
</body>
</html>